Dein Genie 3s, die 5 unbekannten Wesen

Nun soll auch ein Z180-Prozessor Chef im System sein können

Helmut Bernhardt, Arnulf Sopp

Vorbemerkung: Im Folgenden ist viel von "wir" die Rede. Dies aus Gründen der Sprachökonomie. Jeder von uns machte aber in Wirklichkeit das, was er am besten konnte: Helmut die Hardware, Arnulf die Software. Das Pflichtenheft für beides entstand unter Mitwirkung etlicher Gebinde Hopfenbrause.

Die Hardware

Vor längerer Zeit hatten wir unter ähnlichem Titel mal eine Erweiterung für den Genie IIIs beschrieben (1), mit der sämtliche Speicher (User-RAM, Video-RAM, HRG-RAM und Zeichengenerator-RAM) auf die vierfache Größe erweitert werden konnten. Außerdem fiel dabei noch ein SRAM ab, das parallel zum Boot-EPROM arbeitete. Dafür haben wir in den Sockel der Z80-CPU ein Adapter-Board gesteckt, das den Z80 aufnahm und einen schreib- und lesbaren Port bereitstellte, mit dessen Bits die Umschaltung dar Speicherbanks gesteuert wurde.

Über dieses primitive Banking kann z.B. ein Genie 2s-Anwender, der auf eine HD64180-CPU umgerüstet hat (2), nur milde lächeln, wenn er seinen Computer mit 9,2 MHz (gegenüher 7,2 MHz des G3s) fährt. Es galt, dieses Manko beim G3s auszubügeln. Dafür haben wir ein neues Adapter-Board gebaut, auf dem nun kein Z80 (auch kein HD64180), sondern ein Z180 steckt. Der Z180 hat (wie auch der neuere HD64180-PLCC) 20 Adreßleitungen und kann damit über seine MMU und die beiden DMA-Känle 1 Megabyte RAM direkt adressieren.

Um diese CPU so, wie sie gedacht ist, direkt zu nutzen, hätte das riesige Betriebssystem G-DOS 2.3 (oder Calva-DOS 2.4, die auf 1 Megabyte angepaßte Version) vollkommen auf HD64180-MMU-Banking umgeschrieben werden müssen. In über 63 kB SYS- und anderen systemeigenen Files hätten alle OUT-Befehle an die System-Steuerports F9h und FAh gesucht und auf entsprechende Z180-MMU-Befehle geändert werden müssen. Außer viel Arbeit hätte das auch die Kompatibilität mit anderen Computern dieser und ähnlicher Bauart gekostet. Da entschieden wir uns dafür, dem Calva-DOS sein Banking über die Systemteuerports zunächst mal zu erhalten. Die Ports F9h, FAh und FBh (früher F3h) auf dem Adapter-Board haben ihre volle Funktionsfähigkeit behalten.

Nun ist aber der Einsatz eines HD64180 bzw. Z180 witzlos, wenn dessen MMU und DMAC nicht benutzt werden können. Wir haben beide Möglichkeiten eingerichtet: Nach dem Einschalt-Reset sind alle Systemport-Bits auf 0 gesetzt und ein voll G3s-kompatibler Computer incl. Erweiterung auf vierfache Speichergröße liegt vor. Durch Setzen des früher anders belegten Bits D6 in Port FBh kann aber umgeschaltet werden in einen lupenreinen Z180-Computer: alle Banking- und Common-Definitions-Bits der Systemports haben dann keine Funktion mehr. Das RAM wird ausschließlich durch die Adreßleitungen der CPU adressiert.

Nur das Einblenden von memory mapped I/O-Baugruppen in die dafür vorgesehenen physikalischen Adreßbereiche erfolgt, wie im G3s-Modus, durch die entsprechenden Systemport-Bits. Gleichwohl sind deren logische Adressen variabel. Der G3s dekodiert bei ihrer Selektion nur die Adreßbits 0-1. Wie der Z180 derzeit sein physikalisches Megabyte in bis zu drei logische Adreßbereiche unterteilt, indem er mit A12-A19 jongliert, da redet ihm der G3s nicht drein.

Um die Ausmaße eines Adapter-Boards mit diesen Umschaltmöglichkeiten (s. Foto) in Grenzen zu halten, mußten wir zwei PALs einsetzen. PAL 1 erzeugt lediglich die Port-Freigabesignale /OUTFB und /INFB (und noch einige weitere Freigabesignale - s. PAL-Listing), mit denen das Latch 74LS273 und der Lesetreiber 74LS244 angesteuert werden, die den zusätzlichen Port BFh realisieren.

Die eigentliche Steuerung der RAM-Adressierung leistet PAL 2. Durch die Ausgänge /CAS0-/CAS3 wird eine der vier Reihen von 41256er RAM-Chips selektiert. A16 und A17 wählen darin einen 64 kB-Block an. Für die Adressierung im Z180-Modus gelangen die Adressen A16-A19 an das PAL. Im G3s-Modus erfolgt das Banking durch die Bits D6 und D7 von Port F9h sowie D0 und D1 von Port FBh. D7 von Port FBh entscheidet, ob bei logischer Adressierung im eingestellten Common-Bereich (0000h-3FFFh oder E000h-FFFFh) nur innerhalb eines 256 kB-Bereichs oder innerhalb des gesamten 1 MB-Speichers der unterste 64 kB-Block adressiert werden soll.

Der Zugriff auf den eingestellten Common-Bereich wird durch das high aktive Signal COMLH (U84, 74LS00 Pin 11 auf dem CPU-Board) angezeigt. Dieses Signal wird ebenfalls an das PAL geführt (wie auch D1 von Port FBh. das die Auswirkung von COMLH steuert), Durch D6 von Port FBh erfolgt schließlich die Steuerung ob der G3s-Modus oder der Z180-Modus für die Adressierung des RAMs zuständig ist. Das PAL-Assemblerlisting veranschaulicht alle diese Steuerfunktionen.

Damit die Signale/CAS0 - /CAS3 anstelle, der bisherigen Signale /CAS0 - /CAS3 an die RAMs gelangen, ist U43, 74LS125 zu entfernen. Die Signale /CAS0 - /CAS3 des Adapter-Boards werden den RAMs über die Pins 3, 6, 11 und 8 der Fassung von U43 zugeführt. Die an diesen Pins liegenden Pull up Widerstände R57-R60 sollten ausgelötet werden. Die Versorgung mit +5V und GND kann von den Pins 14 und 7 derselben Fassung erfolgen. Und schließlich liefert ihr Pin 9 auch noch das Signal /CAS für den Adapter.

Alle Signale, die dem Adapter-Board vom CPU-Board zugeführt werden müssen, werden über den Stecker CN2 geführt; ebenso die Signale die das Adapter-Board dem CPU-Board liefert. Nur die ursrünglichen Z80-Pin-Signale laufen über den Sockel des Z80.

Der Einsatz eines Z180 bringt aber auch neue Probleme mit sich. Beim Z80 wird der Sysemtakt extern erzeugt und der CPU über Pin 6 eingespeist. Beim HD64180 und beim Z180 wird der Systemtakt, von der CPU geliefert. Dieser Takt wird intern aus einem von außen zugeführten, doppelt so hohen Takt hergeleitet.

Der G3s hat die Möglichkeit (leider auch die Notwendigkeit), zwischen einer hohen Frequenz und den normalen 1,77 MHz des TRS-80 umzuschalten. Diese Umschaltung muß bereits mit dem doppelten Muttertakt erfolgen. Es muß also zwischen 18.332 und 3,55 MHz umgeschaltet werden. Dadurch kann die CPU nicht mehr mit einem normalen Quarz, an den Pins XT und EXT beschaltet werden. Es müssen externe Oszillatorschaltungen benutzt werden. Der jeweils selektierte Takt wird über einen Treiber (74LS125) an den Pin EXT der CPU geschaltet. Die Auswahl des jeweiligen Taktes wird durch die Signale LO (U41, 74LS74, Pin 9) und HI (U41, 74LS74 Pin 8) auf dem CPU-Board gesteuert.

Die bisherige Taktquelle im System wird durch Entfernen von U44, 74LS161 abgeschaltet. Damit der nun von der CPU gelieferte Systemtakt auch auf dem CPU-Board verfügbar wird, müssen die Pins 5 und 6 von U39, 74LS125 aus der Fassung gebogen werden und die Pins 5 und 6 der Fassung miteinander verbunden werden. Die Widerstände R51, R52 und R79 sollten entfernt werden.

Die für das ursprüngliche 256 kB-Banking des G3s verantwortlichen Bits 6 und 7 des Ports F9h (hier als Signale F96 und F97 bezeichnet) sind von den Pins 14 und 13 von U88, 73LS139 zu beziehen.

Die vom Port FBh auf dem Adapter-Board zur Vervierfachung von Video- RAM, Zeichensatz-RAM und HRG-RAM gelieferten Bits 2-5 (FB2-FB5) werden in dieser Reihenfolge an folgende IC-Pins der Hauptplatine geführt:

U13', 73LS157, Pin 6
U13', 74LS157, Pin 3
BIG5 und BIG6, 6264, Pins 23 (diese Pins aus der Fassung biegen)
BIG5 und BIG6, 6264, Pins 2 (diese Pins sind bereits außerhalb der Fasung)

U13' ist ein mit den Pins 1, 8, 15 und 16 huckepack auf U13, 74LS157 gelötetes IC 74LS157. Die weitere Beschaltung dieses ICs gibt folgende Abbildung wieder:

U15' ist ebenfalls ein auf U15, 74LS157 mit den Pins 1, 8, 15 und 16 huckepack gelötetes weiteres IC 74S157.

Die Pins 15 und 16 von BIG1, 6845 sind aus der Fassung zu biegen und mit U13' zu verdrahten.

Schließlich sind noch die Adressen A16 und A17 von CN2 den RAMs gemultiplext zuzuführen. Das Multiplexen bsorgt ein auf U34, 74S157 wiederum mit den Pins 1, 8, 15 und 16 huckepack gelöteter 74S157 (U34'), der an den Pins 13 und 14 mit A16 und A17 zu versorgen ist. Der Multiplex-Ausgang Pin 12 wird über 33 Ω mit den Pins 1 aller RAMs (32x 41256) verbunden.

Zur Vereinfachung des bis hierhin Gesagten sei das alles noch einmal in einer Tabelle wiedergegeben:

Verbindungen von CN2 zum CPU-Board

Stecker CN2  |  CPU-Board
Pin  Signal  |  IC         Typ     Pin
-------------+-------------------------------------------------
1   +5V      |  U43        LS125   14 *   # huckepack gelötete
2   GND      |  U43        LS125    7 *     ICs 74LS(S)157
3   /HI      |  U41        LS74     8       (s. Text und Abil-
4   /LO      |  U41        LS74     9       dungen
5   FB3      |  U13'       LS157    3 #
6   FB2      |  U13'       LS157    6 # 
7   FB5      |  BIG5/BIG6  6264     7
8   FB4      |  BIG5/BIG6  6264    23 (aus der Fassung biegen)
9   F96      |  U88        LS139   14
10  F97      |  U88        LS139   13     * U43 entfernen und
11  /CASO    |  U43        LS125    3 *     Sockel auslöten,
12  COMLH    |  U88        LS139   15       Signale von CN2 an
13  /CAS2    |  U43        LS125   11 *     die Lötpunkte der
14  /CAS3    |  U43        LS125    8 *     entsprechenden Pins
15  /CAS     |  U43        LS125    9 '     des Sockels von U43
16  /CAS1    |  U43        LS125    6 '     anlöten
17  A16      |  U33'       S157    13 #
18  A17      |  U34'       S157    13 #
-------------+-------------------------------------------------

Außerdem sind auf dem CPU-Board noch folgende (z. T. beim Einbau des 4xG3s-Z80-Adapters schon durchgeführten) Änderungen nötig:

Die aus den Fassungen gbogenen Pins 1 von U16, U15 und U16' (alle, 74S157) sind mit Pin 5 von U57, 74S04 zu verbinden. Die Pins 27 von BIG5 und BIG6 (6264), die beide außerhalb der Fassung hängen, werden mit Pin 1 von U54, 74LS32 verbunden. Pin 27 von BIG4, 6264 wird mit Pin 3 von U54, 74LS32 verlötet.

Abb. 2:Pinout des Z180 und seines Sockels
Abb. 3: Auszüge aus der Schaltung

Z180  Signal  Z80-Adapter
-Pin	       -Pin
 14    A0	30
 15    A1	31
 16    A2	32
 17    A3	33
 18    A4	34
 19    A5	35
 20    A6	36
 21    A7	37
 22    A8	38
 23    A9	39
 24    A10	40
 29    A14	 4
 30    A15	 5
 40    D3	 8
 42    D5	 9
 43    D6	10
 10    /INT0	16
  9    /NMI	17
 66    /WR	21
 62    /IORQ	20
  7    /BUSRQ	25	 
  6    /BUSAK	23
  8    /RESET	26
 65    /M1	27
  5    /WAIT	24
 61    /RFSH	28
 68    CLK	 6
von Hand zu verdrahten
zwischen Z180-CPU und
Z80-Adapter-Stecker

CN2-Belegung
Signal  Pin    Signal
  +5V   1   2  GND
/FAST   3   4  /SLOW
  FB3   5   6  FB2
  FB5   7   8  FB4
  F96   9  10  F97
/CAS0  11  12  COMLH
/CAS2  13  14  /CAS3
 /CAS  15  16  /CAS1
  A16  17  18  A17
Die Listings der beiden PALs

PAL16L8
10.03.90  H. Bernhardt, PAL1
Portdecodierung im GIIIs mit Z180 für zusätzl. Systemports

A0 A1 A2 A3 A4 A5 A6 A7 WR GND
RD OUTFB OUTFC OUTF3 IODC INF3 INFC IORQ INFB VCC

/INFB  = /IORQ * /RD * A7 * A6 *A5 * A4 *  A3 * /A2 +  A1 *  A0
/OUTFB = /IORQ * /WR * A7 * A6 *A5 * A4 *  A3 * /A2 +  A1 *  A0
/INFC  = /IORQ * /RD * A7 * A6 *A5 * A4 *  A3 *  A2 + /A1 * /A0
/OUTFC = /IORQ * /WR * A7 * A6 *A5 * A4 *  A3 *  A2 + /A1 * /A0
/INF3  = /IORQ * /RD * A7 * A6 *A5 * A4 * /A3 * /A2 +  A1 *  A0
/OUTF3 = /IORQ * /WR * A7 * A6 *A5 * A4 * /A3 * /A2 +  A1 *  A0
/IODC  = /IORQ *     * A7 * A6 *A5 * A4 *  A3 * /A2


PAL16L8
10.03.90  H. Bernhardt, PAL2
RAM-Steuerung im GIIIs mit Z180

ZA16 ZA17 FB0 FB1 COMLH F96 F97 FB6 FB7 GND
CAS A17 CAS1 CAS2 CAS3 CAS0 ZA18 ZA19 A16 VCC

/ZA16  = /FB6 * /F96
       + /FB6 * COMLH
       +  FB& * /ZA16
/ZA17  = /FB6 * /F97
       + /FB6 * COMLH
       +  FB6 * /ZA17
/CAS0  = /FB6 * /CAS  * /FB1  * /FB0
       + /FB6 * /CAS  * COMLH * /FB7
       +  FB6 * /CAS  * /ZA19 * /ZA18
/CAS1  = /FB6 * /CAS  * /FB1  *  FB0  * /COMLH
       + /FB6 * /CAS  * /FB1  *  FB0  * FB7
       +  FB6 * /CAS  * /ZA19 *  ZA18
/CAS2  = /FB6 * /CAS  *  FB1  * /FB0  * /COMLH
       + /FB6 * /CAS  *  FB1  * /FB0  * FB7
       +  FB6 * /CAS  *  ZA19 * /ZA18
/CAS3  = /FB6 * /CAS  *  FB1  *  FB0  * /COMLH
       + /FB6 * /CAS  *  FB1  *  FB0  * FB7
       +  FB& * /CAS  *  ZA19 *  ZA18
Abb. 4: Layout (lötseitig gesehen) Abb. 5: Bestückungsplan
Abb. 6: aufgebautes, angeschlossenes Board

Die Software

Der Z180 verleitet mit seiner interessanten MMU (Memory Management Unit) und seinem DMAC (Direct Memary Access Controller) geradezu zu Spielereien. Der Leser sei versichert daß wir ihnen auch ausgiebig frönten. So ist es z. B. kein Problem, den Bildschirm oder irgendeinen anderen physikalichen Speicherabschnitt logisch gleich dreimal an verschiedenen Adressen im 64 kB-Fenster der CPU vorliegen zu haben. Hier soll aber ganz bierernst nur vorgestellt werden, was an Änderungen im DOS und Unterstützungen für das DOS prgrammiert wurde, um die Vorteile der neuen CPU nutzen zu können.

Zum Verständnis dessen, was sich nun eigentlich zum Besseren ändert, möchten wir außer den im Hardware-Teil schon genannten Veröffentlichungen noch auf ein Sonderheft des Club-80 (3) und einen Info-Artikel (4) hinweisen, die zum Thema HD64180 erschienen sind. Diese CPU ist softwaremäßig identisch mit dem Z180. Eine erneute Beschreibung der im wesentlichen gleichen Eigenschaften erübrigt sich an dieser Stelle.

Es sind vier Programme, die für den Z180 geändert bzw. neu erstellt wurden:

Patches in zwei verschiedenen Teilen von SYS0/SYS konfigurieren den Z180, um seine Arbeitsgeschwindigkeit und seine MMU auf optimale Werte einzustellen und um seinen DMAC dem System verfügbar zu machen.

SYS26/SYS ist zuständig, um die SYS-Files des DOS in Bank 0 des Speichers zu puffern. Es wird nun nur noch angesprungen, wenn nicht der Rechtspeil gedrückt wurde (was bedeuten würde, daß das DOS nicht gepuffert werden soll). In SYS26 steht nun der DMA-Treiber aus dem neuen SYS0 bereits zur Verfügung, was alle Blockladevorgänge beschleunigt. Die Pufferung der DOS-Moduln benötigt jetzt nicht mehr das aufwendige Banking, das bisher erforderlich war, denn der DMAC kann von überall her den vollen Adreßbereich des Z180 überstreichen.

Eine Änderung in der SYS-Laderoutine, für den DOS-Kern ebenfalls in SYS26 untergebracht, lädt nun die SYS-Programme bei einem DOS-Request mit RST 28h per DMA entsprechend schneller und weniger speicheraufwendig. Daß im Zuge dessen viel Platz in SYS26 frei wurde, der edleren Zwecken zur Verfügung gestellt werden kann, sei nebenbei erwähnt. Zudem ist der besondere Sektorpuffer 3A00h-3AFFh für die SYS-Moduln jetzt nicht mehr notwendig - freier Speicher für andere Anwendungen.

Dann entstand ein Anwenderfile (bei uns TRAP/CMD geheißen), das hauptsächlich Gerald Schröders Illegal-Trap-Programm in Bank 0 und Bank 1 an die logische Adresse 0000h patcht. Hier springt der Z180 nämlich hin, wenn er einen Befehl antrifft, den er nicht kennt (für nähere Erleuterungen möchten wir auf Geralds Artikel im Info Nr. 17 verweisen). Außerdem wird hier die Delay-Routine an 0060h verlangsamt, denn der Z180 arbeitet zu schnell, um mit dem alten Verzögerungsprogramm noch die korrekten Wartezeiten zu erzielen.

Und schließlich zimmerten wir ein Utility-Programm namens SYSTEST/CMD für den DOS-Tüftler (Listing 5). Wenn ein SYS-File, umgeschrieben wurde und nach Murphy's Gesetz noch Fehler enthalten muß, kann es zunächst in der Bank 0 gepuffert und (notfalls bei offenem Floppy-Türchen) von dort aus getestet werden. Damit erübrigt sich gleichzeitig die Notwendikeit, vor dem Test erneut zu booten, um die Datei in die Bank 0 zu kriegen, von wo sie beim gebankten DOS aufgerufen wird.

Alle Änderungen in SYS0 und SYS26 sowie die neuen Files TRAP/CMD und SYSTEST/CMD sind in den Listings wiedergegeben. Weitere Teile, die sich in den beiden SYS-Programmen nicht geändert haben, sind mit LIST OFF ausgespart worden, um den Rahmen dieses Sonderhefts nicht zu sprengen. Dasselbe gilt für TRAP/CMD, soweit es Geralds bereits bekanntes Trap-Programm betrifft. Damit hat der Leser natürlich die Schwierigkeit, daß unklar bleibt, wo die Patches in den Files liegen sollen, und was sich in der Folge sonst noch ändert. Sorry - da können wir nur anbieten, eine Systemdiskette bei Arnulf anzufordern. Die Listings sollen lediglich den Umgang mit den neuen Möglichkeiten des Z180 demonstrieren und die sich ergebenden Voreile besingen.

Es werden auch kleinere Teile der Listings unverständlich bleiben, weil sie sich auf nicht gelistete Programmabschnitte beziehen. Es handelt sich nämlich nicht um besondere Schöpfungen für dieses Sonderinfo, sondern um die Sources für das geänderte DOS. Wenn etwa Labels auftauchen, die sonst nirgends wiederzufinden sind, einfach darüber hinweglesen!

Die genannten Programme sind auch noch längst nicht der Weisheit letzter Schluß. So ist es beispielsweise wünschenswert, einige Konfigurationen des Z180 (WAIT-Zyklen, Refreshes, MMU, vielleicht noch mehr) bereits im Boot-EPROM erledigen zu lassen. So weit sind wir jedoch selbst noch nicht. Gegf. wird man in einem kommenden Clubinfo Weiteres dazu vorfinden.

Soweit Befehle enthalten sind, die zwar der Z180, nicht aber der Z80 kennt, sind sie mit ihren Hex-Entsprechungen als DB-(DEFB-)Statememts eingefügt. ZEUS kennt sie nämlich bedauerlicherweise auch nicht. In einem Kommentar erscheint dann jeweils der Befehl in Z180-Assembler.

Die Programme sind essentiell für das Betriebssystem. Ohne Betriebssystem kein Computer. Daher wird unbedingt empfohlen, alles zunächst mit einer Kopie der Systemdiskette auszuprobieren (für SYS29 kann aber auch SYSTEST gefahren werden!). Erst, wenn sich die Kopie als funktionstüchtig erwiesen hat, hat die alte Systemdisk ausgedient!

Nun zu den Programmen im einzelnen:

SYS0/SYS ist die Seele des G3s. Es ist in seinem ersten Teil eine Fortsetzung von DOS/SYS. Hier ist die erste Modifikation für den Z180 untergebracht: Die Anzahl der WAIT-Zyklen für Speicher- und Portzugriffe wird eingestellt, und zwar auf den schnellstmöglichen Wert. Sollte er sich im Einzelfall als Überforderung des Systems herausstellen, kann der Wert 00h für den Akku mit DDE auf einen anderen Betrag gepatcht werden (XOR A hätte den Akku ebenfalls gelöscht, jedoch ohne die Möglichkeit einer einfachen Änderung). Danach wird die MMU des Z180 auf den Normalzustand des G3s eingerichtet. So kann, etwa für einen DMA (s. u.), die Z180 Speicherkonfiguration in aller Regel geschaltet werden, ohne daß sich etwas am Banking-Zustand ändert.

Die zusätzlichen Befehle (s. Listing 1) werden einfach in die (zuvor per Disassembly gewonnene) Source eingefügt, das Programm neu assembliert. Es besteht aus zwei Sektoren, die in die ersten beiden Sektoren von SYS0/SYS gepatcht werden (das kann z. B. SUPERZAP).

Das Listing 2 zeigt ebenfalls einen Patch in SYS0. Anfangs wird getestet, ob der Rechtspfeil während des Bootens gedrückt wurde. Ist das nicht der Fall, möchte der User das DOS in Bank 0 des Computers puffern, um es später ohne die Laufwerke verfügbar zu haben. Dieser Test war bisher in SYS26 untergebracht. Es erschien uns überflüssig, SYS26 anzuspringen, wenn es bei gedrücktem Rechtspfeil ohnehin gleich wieder verlassen wird.

Dann enthält das Listing einen Treiber für den DMAC des Z180. Er erwartet beim Einsprung in HL die Anfangsadresse des zu transferierenden Blocks, in DE die Zieladresse, in BC den Bytezähler. Bis hierher entspricht der Treiber dem Z80-Befehl LDIR. Neu ist der Inhalt des Akkus, der in seinen beiden Nibbles die Adressen A16-19 des Quell- und des Zielbereichs enthält. So kann ein DMA auf das volle Megabyte des Z180-Adressraums zugreifen.

Die internen DMAC-Register SAROB (Kanal 0, Quelle, Bits 16-19) und DAROB (Kanal 0, Ziel, Bits 16-19) werden nur in ihren unteren 4 Bits beachtet. So war es zur Laufzeit- und Platzersparnis möglich, auf das Löschen der oberen 4 Bits zu verzichten: Der Befehl RRD (Zeile 94) rotiert die hier relevanten Bits 3-7 ins untere Nibble von DAROB, der folgende Befehl LD (scrphys),A packt einfach den kompletten Akku mit seinem unwichig gewordenen oberen Nibble nach SAROB.

In Zeile, 102 wird die G3s-MMU deaktiviert, indem in Port FBh das Bit 6 gesetzt wird (s. Hardware-Teil). Nur so kann der DMA-Treiber über das ganze Megabte verfügen. Ansonsten könnte nur das 64 kB-Fenster, das gerade vom G3s bearbeitet wurde, vom DMAC überstrichen werden. Also ist beim Einsprung in die DMA-Routine unbedingt darauf zu achten, daß die MMU-Konfiguration des Z180 mit der des G3s zumindest in wichtigen Speicherabschnitten übereinstimmt: Der Treiber muß sich nach dem Umschalten selber wiederfinden können, der Stack muß ebenfalls an derselben logischen Adresse vorliegen. Erst nach dem Rückschaltbefehl (Zeile 111) ist Entwarnung gegeben.

Bei der Rückkehr aus dem Programm enthalten alle Register ihren alten Wert, der gerettet wurde. Im Gegensatz dazu gibt der Befehl LDIR die Quell- und Zielregister um den Betrag des Bytezählers erhöht zurück. BC selbst ist dann 0000h. Dieser Service hätte mit in den Treiber eingebaut werden können, der verfügbare Platz reichte jedoch nicht. Zudem haben beide Möglichkeiten ihre Vor- und Nachteile.

An dieser Portion von SYS0 ist nur der filerelative Sektor 10h interessant. Das ist der diskreltive Sektor 15h. Die Source gem. Listing 2 wird assembliert. Von der so entstandenen CMD-Datei muß nun (mit SUPERZAP oder wie auch immer) der erste Sektor nach SYS0 kopiert werden, und zwar in den eben bezeichneten Sektor. Wichtig ist, daß dieser Sektor des CMD-Programms genau am relativen Byte FFh aufhört, also ganz unten rechts. Danach, im nächsten Sektor, folgt der Rest, der mit einem neuen Record-Header beginnt. Bis dorthin können NOPs bzw. DW 0000h- oder DB 00h-Statements eingefügt werden. Um das Puzzle zu erleichtern, folgt hier ein Sektor-Dump der den relativen Sektor 10h von SYS0 wiedergibt:


file:  SYS0/SYS     drv: 0    frs: 0010h     drs: O015h
00:  018C 0032 3E40 D3F9 FBC1 D1E1 C9E5 D5C5    2 >@
10:  3E01 F3D3 F9C3 0AF0 3A07 43F6 3032 8232  >       : C 02 2
20:  E60F FE04 2o11 3AF8 42CB 5F28 0A3A 4038        : B  ( :@8
30:  E640 3EFC CC02 4421 7F32 1180 4401 0B00   @>   D! 2  D
40:  EDB0 1180 4421 0042 CD24 4428 0BFE 1820      D! B $D(
50:  2B3E 0132 0743 180E EBCD 284C 201E 1162  +> 2 C   (L   b
60:  32D5 1198 31E9 2100 3011 AD4E 0100 023E  2   1 ! 0  N   >
70:  10CD BD35 E1F1 32F9 42C3 6744 F5CD C901     5  2 8 gD
80:  3E46 EF4F 564c 782F 5359 533A 300D 0170  >F OVLx/SYS:0  p
90:  BB35 22F0 35ED 53F3 35ED 43F6 35E5 21F5   5" 5 s 5 C 5 #
A0:  3577 ED67 32F2 3521 F735 C501 2708 F5D8  5w g2 5! 5
B0:  FBF5 F640 F3D3 FBED 9B01 3102 ED9B F1D3     @      1
C0:  FBF1 C1E1 C940 0200 0000 0000 0000 0000      @
D0:  0000 0000 0000 0000 0000 0000 0000 0000
E0:  0000 0000 0000 0000 0000 0000 0000 0000
F0:  0000 0000 0000 0000 0000 0000 0000 0000

Es ist ausreichend, das im Hex- und im ASCII-Teil gelb hinterlegte Zählbyte des Record-Headers (rel. Sektorbyte 8Fh) genau so zu zappen um den Rest auszunullen. Dann dürfte nichts mehr schiefgehen. Voraussetzung ist, daß das Zählbyte auch an dieser Stelle steht. Ansonsten muß es eben auf andere Weise angepaßt werden, damit das letze Datenbyte des Sektors an der sektorrelativen Stelle FFh zu liegen kommt.

Listing 3 behandelt ein paar Änderungen in SYS26. Dort wird, wie schon erwähnt, das Puffern des DOS im Speicher veranlaßt. Gleichzeitig wird der DOS-Kern gepatcht: Soll ein SYS-File mit RST 28h geladen werden, wird nicht mehr die Floppy angeworfen. Statt dessen wird das Programm aus der Bank 0 geholt.

Dafür dient ein besonderes Minimal-DIR: Pro SYS-Modul enthält es zwei Bytes. Das erste ist das MSB der Pufferadresse in Bank 0. Da das LSB immer 00h ist, da also jedes SYS-File am Anfang eines 256Byte-Blocks beginnt, genügt das MSB. Das zweite Byte gibt die Länge des Files in Sektoren an. Gepuffert werden nur die Programme SYS1-19. GDOS/SYS, IHHALT/SYS und SYS0/SYS haben hier keine Bedeutung und bleiben deshalb auf der Floppy. Ihr Platz im Mini-DIR ist mit Nonsene (GDOS) bzw. mit Nullen (INHALT und SYS0) gefüllt.

Eine spezielle Laderoutine für SYS-Programme liest dieses DIR und transferiert dann die Sektoren ursprünglich nach 3A00h, einen besonderen Sektorpuffer. Von dort wird das File sektorweise in den Overlay-Speicher des DOS geladen und schließlich angesprungen.

Hier die Änderungen die die Vorteile des Z180 ausnutzen: Der DMAC benötigt kein Banking, um Daten zu transportieren. Die Unterprogramme, die das DOS in den Speicher laden und es später beim Betrieb von dort wieder abholen, konnten deshalb wesentlich verkürzt (und damit beschleunigt) werden.

Das UP putsys puffert die SYS-Files. Dazu wird zunächst der Teil von INHALT/SYS ab 5200h in den Speicher geladen, der SYS-Programme enthält. Der Platzbedarf von 0800h Bytes zerstört dabei nach Reset den Inhalt des Anwenderspeichers. Daher wird (ab Label boot) zunächst dieser Bereich in die Bank 1 gerettet um später restauriert zu werden. Dann wird das besondere SYS-DIR im Block 3900h eingerichtet. Die ersten Bytes des Blocks müssen ausgenullt werden, damit bei einem DOS-Request nicht versucht wird, INHALT oder SYS0 aus der Bank 0 zu holen; die Nullen sind Signalbytes für das Verbot. Anschließend wird ab 4100h in Bank 0 das restliche DOS abgelegt.

Mit der Restauration des Anwenderspeichers und dem Transfer des SYS-DIR an seine endgültige Adresse 4000h in Bank 0 endet dieser Teil von SYS26.

Der Patch im DOS-Kern, der SYS-Dateien aus der Bank 0 holt, ist anschließend gelistet. Der verfügbare Speicherplatz im residenten Teil von SYS0 (ab 4BE1h) reicht dazu nicht aus. Ein notwendiges Unterprogramm macht deshalb an der Stelle 3738h weiter (was auch bisher schon so war). Dieses UP kann nun per DMA auf aufwendiges Banking verzichten, das zuvor nötig war. Immerhin 13 Bytes wurden frei die Arbeitsgeschwindigkeit stieg enorm.

Das nächste Programm, das mit Listing 4 hier vorgestellt werden soll, ist in dieser Form ein reines Anwender-File. Wegen seiner Wichtigkeit erscheint es sinnvoll, es später einer SYS-Datei einzuverleiben, vielleicht gleich SYS26. Es nimmt ein paar Patches im BASIC-Interpreter vor, die dem Z180 gerecht werden.

Seine Arbeitsgeschwindigkeit ist deutlich höher als die des Z80, weil viele Befehle weniger Taktzyklen beanspruchen. Dadurch beschleunigt sich die Delay-Routine an 0060h bedenklich. Wartezeiten, die dort z.B. für den Floppy-Controller abgetrödelt werden, sind nun zu kurz. Eine geringfügige Änderung schafft Abhilfe, so daß die Verzögerungen fast genau mit der alten Zeiten identisch werden:

In der alten Version wird mit einem JR NZ-Befehl in die Schleife zurückverzeigt, wenn der Zähler BC noch nicht abgelaufen ist. Die neue Variante durchläuft zuerst den Befehl RET Z, und zwar jedesmal. Hat der Zähler noch etwas Stoff, geht es mit bedinungslosem JR zurück in die Schleife. Der zusätzliche Return-Befehl, der bei jedem Schleifendurchlauf gelesen werden muß, kostet die erwünschten Taktzyklen zur Verlangsamung.

Dies alles trifft freilich nur bei der langsameren Takt-Fequenz von 1,77 MHz zu, die über Port FAh, Bit 6 gewählt werden kann. Alle kritischen Verzögerungsschleifen des DOS werden jedoch, soweit uns bekannt, erst nach dieser Taktumschaltung durchlaufen. Wo nicht, ist die verkürzte Laufzeit durch den High-Speed-Takt des Z180-Boards immerhin noch erträglich zu schnell.

Direkt an die Delay-Schleife schließt sich der NMI-Service an. Der TRS-80 benutzt ihn als Reset-Ersatz. Beim G3s ist der NMI unbenutzt (hard- warermäßig übrigens auch nicht zugänlich - die freien Tasten links oben und unten in der Haupttastatur können mit dem NMI-Pin der CPU verdrahtet werden). Unsere Serice-Routine läßt einfach nur die Interrupts wieder zu. Damit können z. B. die Dreitastenbefehle aktiviert werden, wenn man etwa jederzeit mit dem Debugger den Speicher und die Reister im Auge haben möchte.

Hauptbestandteil dieses Programms ist jedoch Gerald Schröders Error-Trap-Routine. Dorthin verzweigt der Z180, wenn ein ihm unbekannter Opcode angetroffen wird. Auch hier möchten wir wieder auf schon erschienene Erklärungen verweisen, um Wiederholungen zu vermeiden (Info Nr. 17).

Beim Einsprung am Label start wird der Beginn der Trap-Routine, nämlich ein Sprung nach 1650h, nach 0000h ff. gezapt. Vor dem eigentlichen JP findet sich ein NOP. Hier kann der User bei einem Trap-Interrupt auch etwas anderes als diesen Sprung veranlassen. Mit F7h (RST 30h) an dieser Stelle wird z. B. in den Debuger gesprungen. Besonders in der Experimentierphase, wenn der Z180 noch neu ist, wird man das gelegentlich wollen.

Bei 1650h sind die BASIC-Befehle im Klartext abgelegt. Das Trap-Programm überschreibt sie. Wer gerne in BASIC arbeitet, kann so natürlich nicht verfahren. Eine andere Adresse muß her. In einem kommenden Info wird die Lösung des Problems zu lesen sein.

In Bank 1 soll ebenfalls Geralds Trap-Programm verfügbar sein. Dort ist ab 0000h Platz dafür, ein JP erübrigt sich. Diese neue Ladeadresse erfordert die Relokation aller festen Adressen im Trap-Pogramm. Das beginnt mit Zeile 188 im Listing. Der Vorgang ist etwas verzwickt. Wir möchten aber darauf verzichten, ihn über die Kommentare im Listing hinaus zu erleutern. Dies kann kein Lehrbuch über Z80-Assembler sein). Alle kritischen Adressen wurden mit einem Label versehen, addr1-addr15. addr1 ist im Listing sichtbar, die übrigen nicht. Diese Labels finden sich in der Tabelle addrtab wieder.

Nur ein Detail soll beleuchtet werden. Weil der Leser u. U. nicht gleich RAMDISK (s. u.) über JP 4405h abfahren möchte: Beim Sprung nach 4405h wird über den Requestcode 63h nach SYS1 verzweigt. Mit, diesem code im Akku (ACHTUNG: mit etlichen anderen nicht!) wird als erstes der Stack neu eingerichtet, weil dabei eine Rückkehr zum Aufrufer nicht stattfinden soll. Für den CALL dma und die PUSHes und POPs im DMA-Treiber genügt ein vorübergehender Stack an beliebiger Stelle. Er wird hier (zeile 199,) kurz und schnell unter die Trap-Routine gelegt.

Bei einem anderen Aussprung aus TRAP/CMD, ganz besonders mit RET, muß zuvor der Original-Stack unbedingt gerettet und nachher restauriert werden. Das geht mit dem Strickmuster nach dem auch die Zeilen 192 und 189/190 (in dieser Reihenfolge!) funkionieren. Das hätten wir unter Dreingabe von ein paar Bytes und Mikrosekunden natürlich auch hier so machen können, aber dieser schlitzohrigere Weg war halt gar zu verlockend.

Nachdem nun die Trap-Routine auch nach Bank 1 tranferiert ist, wird zuletzt die RAM-Disk des G3s aktiviert. Dieser Programmbestandteil wäre verzichbar. Da wir aber immer mit der RAM-Disk arbeiten, kann das getrost gleich mit erledigt weren. Wenn nein: Unbedingt die Aussprungs-Bedingungen beachten (Stack, s. o.). Übrigens ist der ursprüngliche Name des Proramms MEMDISK/CMD. Hier handelt es sich um eine geänderte Version.

SYSTEST transferiert ein CMD-Programm, das als SYS-File des DOS dienen soll, in die Bank 0, von wo die SYS-Dateien mit RST 28h aufgerufen werden. Prinzipiell geht das mit jeder Datei, in der Regel wird es sich jedoch um neue Versionen eines echten DOS-Moduls handeln.

Es beginnt gem. Listing 5 mit der Prüfung, ob das DOS überhaupt schon in Bank 0 gepuffert ist. Das ist die Voraussetzung, weil sonst die neue Datei nicht mit RST 28h erreichbar wäre. Sollte das noch nicht geschehen sein, wird SYS26 (s. d.) mit FCh im Akku zuerst aufgerufen, um das DOS zu banken. Zum Test dient ein Lückenfüller-NOP, das bei der geänderten SYS-Laderoutine an der Stelle 4C0Bh stehen muß.

Das eigentliche Arbeitsprogrogramm klärt nun zunächst, was für ein CMD-File in we1ches SYS-Programm kopiert werden soll. Diese Angaben können jedoch schon beim Aufruf gemacht werden, denn die Befehlssyntax ist

SYSTEST<,FILSPEC<,SYSNR>>.

Wenn der zweite oder beide Befehlsparameter weggelassen werden, wird nach ihnen gefragt. Dabei wird FILESPEC in der üblichen Weise, z.B. auch mit Laufwerksnummer, eingegeben. SYSNR ist nur eine Dezimzahl für SYSx/SYS.

In der Bank 0 befinden sich nur die Files SYS1-29. Das Programm prüft daher auch, ob mit SYSNR eine zulässige Datei benannt wurde. Außerdem darf die Testdatei höchstens so lang sein wie die Zieldatei in Bank 0. Sonst würde das dahinter liegende SYS-File übesschrieben werden. In diesem Falle, wie überhaupt bei jedem denkbaren Fehler, bricht das Pragramm mit einer DOS-Fehlermeldung ab. Dies geschieht mit einem Sprung nach DOSERR (4409h), wo der Stack neu eingerichtet wird. Daher durfte getrost ignoriert werden, ob gerade ein PUSH oder CALL den Stack verbogen hat.

Auch hier sollen allzu weitschweifige Erklärungen des Programms vermieden werden. Die Kommentare mögen genügen. Für die ausgiebigen Aufrufe etlicher DOS-Routinen möchten wir auf Grossers "DOS-Buch" (5) verweisen, ohne das wir es übrigens wohl auch nicht geschafft hätten. Es sei nur darauf hingewiesen, daß wieder der DMA benutzt werden konnte, und daß ein komfortabler Befehl des Z180. MLT ww (3), das Umrechnen einer Dezimal- in eine Binärzahl erleichterte (zeile 31/32).

In der kommenden Zeit, liegt eine interessante Aufgabe in der weiteren Umgestaltung des Systems auf den Z180 hin. Wir würden uns freuen, wenn auch die Nachbauer des Z180-Boards gelegentlich mit Software im Club-Info vertreten wären. Vorschlag: Auch und gerade die RAM-Disk kann von der neuen CPU profitieren.

Literatur:

(1) Bernhardt, Sopp, Sonder-Info "Dein GIIIs, die 4 unbekannten Wesen", Michelbach,/Bilz 1986

(2) Bernhardt, "512k-RAM-Addressierung mit flexibler MMU", Club-Info 18, Michelbach/Bilz 1987

(3) Bernhardt, Schröder Sonder-Info "HD64180". Gschlachtenbretzingen 1989

(4) Schröder, "Z80, HD64180 und Illegals", Club-Info 17, Michelbach/Bilz 1987

(5) Grosser, "Das DOS-Buch", Aachen 1985


00001 ;Listing 1: Patch in SYS0/SYS, rel. Sektor 00h: 00002 ;SYS0/SYS konfiguriert den Z180 für G-DOS 00003 ;FRS 006 (hier nicht interessierende Teile sind mit LIST OFF 00004 ;DRS 05h ausgespart - erkennbar an den springenden Zeilennummern) ; mit LIST OFF ausgespart 00035 4010 3E00 00036 m4d10 LD A,00h ;A <- 00: Memory: 0 WAITs, I/O: 1 WAIT 4012 ED 00037 DB 0edh,39h,32h ;OUT0(32h),A 4015 3E83 00038 LD A,83h ;RFSH alle 80 Zyklen 2 Zyklen lang 4017 ED 00039 DB 0edh,39h,36h ;OUT0(36h),A 4D1A 21624E 00040 LD HL,mmutab ;Tabelle der MMU-Werte 4010 013803 00041 LD BC,endtab-mmutab'256+38h ;3 Werte ab Port 38 4020 ED 00042 DB 0edh,93h ;001110 (Werte ausgeben) ; mit LIST OFF ausgespart 00208 00209 ;Tabelle zum Einrichten der MMU des 2180 4E62 10 00210 mmutab DB 10h ;Common 1 ab 1.1000 4E63 10 00211 DB 10h ;Bank-Area ab 1.4000 4E64 E4 00212 DB 0e4h ;hierfür die logischen Adressen 00213 endtab 00000 Fehler 00001 ;Listing 2: Patch in SYS0/SYS im relativen Sektor 10h: 00002 ;SYS0/SYS stellt einen DMA-Treiber zur Verfügung 00003 ;FRS 10h (unteressierende Teile sind mit LIST OFF 00004 ;DRS 15h ausgespart - erkennbar an springenden Zeilennummern) 00005 ; mit LIST OFF ausgespart 00037 ;Test auf Rechtspfeil: DOS banken oder nicht? (früher in SYS26/SYS) 3229 3A4038 00038 LD A,(m3840) ;Tastatur Steuerzeichen 322C E640 00039 AND 40h ;Rechtspfeil gedrückt? (nein: DOS banken) 322E 3EFC 00040 LD A,0fch ;Requestcode für SYS26/SYS 3230 CCO244 00041 CALL Z,m4402 ;mit OST 28h SYS26 aufrufen (DOS banken) 3233 217F32 00042 m322c LD HL,m3275 ;Filename 'OVL4/SYS' ; mit LIST OFF ausgespart 00081 00082 ;Unterprogr. für DMA: HL = LSW Quelle, DE = LSW Ziel, BC = Bytezähler, 00083 ;A Bit 0-3 = MSB der Quelle, A Bit 4-7 . MSB des Ziels 00084 ;(MSB . most significant byte, A16-19, obere 4 Bits der Adresse, 00085 ; LSW . less " word, A0-15, untere 16 " " " ) 00086 35BB 00087 ORG 35bbh 35BB 22F035 00088 dma LD (srclog),HL ;Quellbereich log. LSW x.HL 35BE ED53F335 00089 LD (dstlog),DE ;Zielbereich log. LSW x.DE 35C2 ED43F635 00090 LD (bytcnt),BC ;Bytezähler 0.BC 35C6 E5 00091 PUSH HL 35C7 21F535 00092 LD HL,dstphys ;Zielbereich Phys. MSB Ah.DE 35CA 77 00093 LD (HL),A ;MSB setzen (016-19: Bit 4-7) 35CB ED67 00094 RRD ;Nibbles rotieren (A16-19: Bit 0-3) 35CD 32F235 00095 LD (srcphys),A ;Quellbereich phys. MSB Al.HL 35D0 21F735 00096 LD HL,tabend ;Beginn der DMA-Wertetabelle 35D3 C5 00097 PUSH BC 35D4 012708 00098 LD BC,0827h ;8 Werte ab Port 27 abwärts 35D7 F5 00099 PUSH AF 35D8 DBFB 00100 IN A,(0fbh) ;Systembyte 2 35DA F5 00101 PUSH AF ;retten 35DB F640 00102 OR 40h ;MMU des Z180 freigeben 35DD F3 00103 DI 35DE D3FB 00104 OUT (Ofbh),A 00105 ; OTDMR ;DMAC aufsetzen 35E0 ED 00106 DB 0edh,9bh ;(Hex-Entsprechung des Befehls) 35E2 013102 00107 LD BC,0231h ;2 Werte ab Port 31 abwärts 00108 ; OTDMR ;Rest aufsetzen u. DMA abschießen 35E5 ED 00109 DB 0edh,9bh 35E7 F1 00110 POP AF ;altes Systembyte 2 35E8 D3FB 00111 OUT (0fbh),A 35EA F1 00112 POP AF 35EB C1 00113 POP BC 35EC E1 00114 POP HL 35ED C9 00115 RET 00116 00117 ;Wertetabelle für den DMA-Controller (fallende Reihenfolge für OTDMR) 35EE 40 00118 DB 40h ;30, DSTAT: Kanal 0, Zustand 'scharf' 35EF 02 00119 DB 02h ;31, DMODE: Speicher zu Speicher, Burst-Modus 35F0 0000 00120 srclog DW 0000h ;20/1, SAROL/H: Duelladresse LSW x.#### 35F2 00 00121 srcphys DB 00h ;22, SAR0B: MS8 #.xxxx 35F3 0000 00122 dstlog DW 0000h ;23/4, DAR0L/H: Zieladresse LSW x.#1114 35F5 00 00123 dstphys DB 00h ;25, DAROB: MSB #.xxxx 35F6 0000 00124 bytcnt DW 0000h ;26/7, BCR0L/H: Bytezähler für die Programmlänge 35F7 00125 tabend EQU $-1 ;Ende der Tab., womit der Zeiger HL geladen wird 00000 Fehler 00001 ;Listing 3: Patch in SYS26/SYS: 00002 ;SYS26/SYS neue Routine zum Puffern und Laden von SYS-Files 00003 ;in Bank 0 des User-RAMs 00004 ;(hier nicht interessierende Teile sind mit LIST OFF 00005 ;ausgespart - erkennbar an den springenden Zeilennummern) 00006 ; mit LIST OFF ausgespart 35BB 00012 dma EQU 35bbh ;Adresse des DMA-Treibers ; mit LIST OFF ausgespart 00331 00332 ;UP zum Übertragen von SYS-Files in die Bank 0 00333 ; E: HL = Adresse RAM-DIR-Eintrag 00334 ; D = Länge des Files in Sektoren 00335 ; E = Adreß-MSB des Files in der Bank 0 00336 4F1C E5 00337 putsys PUSH HL ;39xx, DIR-Eintrag des akt. SYS-Files 4F1D D5 00338 PUSH DE ;E . MSB des SYS-Files, D . Länge in Skt. 4F1E C5 00339 PUSH BC 4F1F F5 00340 PUSH AF 4F20 73 00341 LD (HL),E ;MSB der Zieladresse ins SYS-DIR 4F21 23 00342 INC HL ;nächste Stelle 4F22 72 00343 LD (HL),D ;Zählbyte eintragen 4F23 210042 00344 LD HL,m4200 ;Sektorpuffer 4F26 010001 00345 LD BC,0100h ;Länge 1 Skt. 4F29 53 00346 LD D,E ;DE <- Zieladresse (MSB) des Sektors 4F2A 59 00347 LD E,C ;(LSB immer =00) 4F2A 3E01 00348 LD A,01h ;von Bank 1 nach Bank 0 4F2D CDB835 00349 CALL dma ;Block übertragen 4F30 F1 00350 POP AF 4F31 C1 00351 POP BC 4F32 D1 00352 POP DE 4F33 E1 00353 POP HL 4F34 FB 00354 EI 4F35 C9 00355 RET 00356 00357 ;Einsprung bei Boot: RAM-Inhalt retten, SYS-Files in der Bank 0 puffern 4F36 210052 00358 boot LD HL,m5200 ;Beginn des zu überschreibenden Bereichs 4F39 110008 00359 LD DE,0800h ;Zwischenpuffer dafür in Bank 1 4F3C 42 00360 LD B,D ;BC <- 0800, zu überschreibender Bereich 4F3D 48 00361 LD C,E 4F3E E5 00362 PUSH HL 4F3F D5 00363 PUSH DE 4F40 3E11 00364 LD A,11h ;von Bank 1 nach Bank 1 4F42 CDB835 00365 CALL dma ;RAM-Inhalt retten 4F45 ED73914E 00366 LD (m4f10),SP ;alten Stach retten 4F49 CDCB4E 00367 CALL m4f55 ;DIR-Sektoren mit SYS-Entries laden 4F4C 210039 00368 LD HL,m3900 ;vorläufiger SYS-DIR-Puffer 4F4F 110139 00369 LD DE,m3900+1 ;zum Ausnullen vorbereiten 4F52 78 00370 LD A,E ;A <- 01, Zähler für 1 Durchgang 4F53 32074F 00371 LD (filelen),A ;dort ablegen 4F56 0E06 00372 LD C,06h ;Zähler 6 Bytes (f3 = 00 seit m4f55) 4F58 75 00373 LD (HL),L ;1. Byte des SYS-DIR-Puffers ausnullen 4F59 EDB0 00374 LDIR ;Rest ausnullen (hier schneller als DMA) 4F5B 1E41 00375 LD E,41h ;ab Page 4100 die SYS-Files puffern ; mit LIST OFF ausgespart 4FA0 E1 00407 POP HL ;Adresse des gepufferten RAM-Inhalts 4FA1 D1 00408 POP DE ;seine frühere Ladeadresse 4FA2 44 00409 LD B,H ;BC <- 0800h, Blocklänge (C=00 seit LDIR) 4FA3 3E11 00410 LD 4,11h ;von Bank 1 nach Bank 1 4FA5 CDBB35 00411 CALL dma ;RAM-Inhalt ab 5200h restaurieren 4FA8 210039 00412 LD HL,m3900 ;Puffer für SYS-DIR 4FAB 110040 00413 LD DE,m4000 ;endgültige Adresse dafür in Bank 0 4FAE 0601 00414 LD B,01h ;Länge 256 Bytes (C = 00) 4F80 AF 00415 XOR A ;A - 00: Bank 0 -> Bank 0, 'kein Fehler' 4F81 C3BB35 00416 JP dma ;Block übertragen und zurück ins DOS 00417 00418 ;Patch im DOS-Kern: Einsprung bei DOS-Request mit RST 28h 03D03 00419 offs4 EAU $-4be1h ;Abstand zur Ladeadresse 4FB4 3E40 00420 m4be1 LD A,m4000/256 ;DIR des gebankten DOS (Adreß-MSB) 4F66 323D37 00421 LD (addrmsb-offs3),A ;in Laderoutine patchen 4FB9 CD3837 00422 CALL m3738-offs3 ;in den Sektorpuffer übertragen 4FBC 2642 00423 LD H,m4200/256 ;Sektorpuffer (MS8) 4FBE 341743 00424 LD 4,(4317h) ;SYS-Kenner 4FC1 07 00425 RLCA ;2 (wegen 2 Bytes pro Eintrag) 4FC2 6F 00426 LD L,A ;als LSB des Zeigers laden 4FC3 7E 00427 LD A,(HL) ;Adreß-MSB des SYS-Files in Bank 0 4FC4 323D37 00428 LD (addrmsb-offs3),A ;in die Laderoutine patchen 4FC7 23 00429 INC HL ;auf Längenbyte stellen 4FC8 7E 00430 LD A,(HL) ;laden 4FC9 B7 00431 OR A ;= 00? (dann INHALT/SYS oder SYSO/SYS) 4FCA 2815 00432 JR Z,m4c0e ;Fehler, falls ja (nicht vorhanden) 4FCC 213837 00433 LD HL,m3738-offs3 ;modifizierte Sektor-Laderoutine 4FCF 226D4C 00434 LD (4c6dh),HL ;in SYSO patchen 4FD2 CD2B4C 00435 CALL 4c2bh ;SYS-File laden 4FD5 221E4C 00436 LD (4c1eh),HL ;Startadresse des SYS-Files dort patchen 4FD8 213644 00437 LD HL,4436h ;alte Sektor-Laderoutine 4FD8 226D4C 00438 LD (4c6dh),HL ;restaurieren 4FDE 00 00439 NOP ;Füller bis zur alten Fortsetzung 4FE1 00440 m4c0e EQU §+2 00441 00442 ;neue Laderoutine für SYS-Files 18A7 00443 offs3 EQU $-3738h 4FDF E5 00444 m3738 PUSH HL 4FE0 D5 00445 PUSH DE 4FE1 C5 00446 PUSH BC 4FE2 210000 00447 LD HL,0000h ;Duellblock in Bank 0 4FE4 00448 addrmsb EQU $-1 ;MSB wird jeweils gepatcht 4FE5 7C 00449 LD A,H ;Adreß-MSB 4FE6 3C 00450 INC A ;100h Bytes weiter 4FE7 323D37 00451 LD (addrmsb-offs3),A ;MSB für nächsten Block patchen 4FEA 3E10 00452 LD A,10h ;aus Bank 0 nach Bank 1 4FEC 110042 00453 LD DE,m4200 ;Sektorpuffer 4FEF 010001 00454 LD BC,0100h ;Sektorlänge 4FF2 CDBB35 00455 CALL dma ;Block übertragen 4FF5 C1 00456 POP BC 4FF6 D1 00457 POP DE 4FF7 E1 00458 POP HL 4FF8 AF 00459 XOR A ;Flag 'kein Fehler' 4FF9 C9 00460 RET 00000 Fehler 00001 ;Listing 4: Einige Änderungen für den Z180 im BASIC-Interpreter 00002 ;TRAP/CMD Hauptsächlich Delay und Illegal-TRAP-Routine 00003 ; (Gerals Schröders TRAP-Routine idt mit LIST-OFF aus- 00004 ; gespart, nachzulesen Club-Info Nr. 17, nur ihr 00005 ; GIIIs-spezifischer Anfang ist gelistet 00006 0000 00007 target1 EQU 0000h ;Zieladresse der Trap-Routine in Bank 1 1650 00008 target0 EQU 1650h ;dto. in Bank 0, vorläufig im BASIC Bereich 35BB 00009 dma EQU 35BB ;Aresse des DMA-Treibers 00010 5200 00011 ORG 5200h 00012 00013 ;Trap-Einsprung für Adresse 9 5200 00 00014 lowmem NOP ;Platz für eventl. F7 (RST 30, Debugger) 5201 C35016 00015 JR target0 ;Einsprung bei Trap-Interrupt 00016 00017 ;Einsprung der Warteschleife und NMI-Routineab Adresse 0060 5204 0B 00018 delay DEC BC ;(alter Teil der Delay-Routine 5205 78 00019 LD A,B ;bleibt unverändert) 5206 B1 00020 OR C 5207 C8 00025 Ret Ẑ ;neu: wird immer bearbeitet (Verrzögerung) 5208 18FA 00022 JR delay ;jetzt Laufzeit etwa wie Z80 00023 520A FB 00024 nmi EI ;NMI: Interrupt zulassen 520B C9 00025 RET 00026 00027 ;Fehlerbehandlung bzw. Illegal-Simulation nach einem Trap-Interrupt 00028 ;vorläufige Version: kein anderer RST 00h außer TRAP berücksichtigt! 388C 00029 offs EQU $-target0 ;Abstand zur Arbeitsadresse 520C F3 00030 trap DI ;Interrupt aus 520D F5 00031 PUSH AF ;Akku und Flags retten 520E DBFA 00032 IN A,(0fah) ;System-Byte 1 5210 32FA16 00033 LD (fsbuff-offs),A ;puffern 5211 00034 addr1 EQU $-2 5213 E6DF 00035 AND 0dfh ;evtl. Schreibschutz aufheben 5215 03FA 00036 OUT (0fah),A ;System-Byte neu ausgeben 00171 52C7 DBFA 00172 start IN A,(0fah) ;System-Byte 1 52C9 E6DF 00173 AND 0dfh ;evtl. Schreibschutz aufheben 52CB F3 00174 DI 52CC D3FA 00175 OUT (0fah),A ;neu ausgeben 52CE 240052 00176 LD HL,(lowmem) ;Code für Adresse 0000h 52D1 00177 LD (0000h),HL ;am Zielort ablegen 52D4 1A0202 00178 LD HL,(lowmem+2) ;Fortsetzung, insgesamt 4 Byte 52D7 220200 00179 LD (0003h),HL 52DA 52DD 00180 LD HL,delay ;neue Verzögerungs-Routine 52DD 116000 00181 LD DE,0060h ;Zieladresse 52E0 010B00 00182 LD BC,trap-delay ;Länge 52E3 EDB0 00183 LDIR ;(wenige Bytes) LDIR schneller als DMA 52E5 115016 00184 LD DE,target0 ;Zieladresse (HL bereits auf Quelle trap) 52E8 018800 00185 LD BC,atart-trap ;Länge 52EB 3E01 00186 LD A,01h ;von Bank1 nach Bank0 52ED CDBB35 00187 CAll dma ;Block übertragen (schneller als LDIR) 52F0 060F 00188 LD B,ebdtab-addrtab/2 ;Anzahl zu relozierender Abressen 52F2 311E53 00189 adrlop LD SP,addrtab ;Stack auf Adressentabelle 52F3 00190 spbuff EQU $-2 52F5 E1 00191 POP HL ;eine Adresse abholen 52F6 ED73F352 00192 LD (spbuf),SP ;Tabelle als Stack retten 52FA F9 00193 LD SP,HL ;dortige Adresse = Stack 52FB E1 00194 POP HL ;dortiges Word abholen 52FC ED52 00195 SBC HL,DE ;auf neue Basisadresse umrechnen 52FE E5 00196 PUSF HL ;neues Woed ablegen 52FF 10F1 00197 DJNZ addrlop ;bis alle Adressen bearbeitet 5301 210C52 00198 LD HL,trap ;Adresse der Trap-Routine 5304 F9 00199 LD SP,HL ;unterhalb neuer Stack 5305 110000 00200 LD DE,target1 ;Zieladresse in Bank 1 5308 01BB00 00201 LD BC,start-trap ;Länge der TRAP-Routine 530B 3E11 00202 LD 4,11h ;von Bank 1 nach Bank 1 530D CDBB35 00203 CALL dma ;TRAP-Routine nach Bank 1 verladen 5310 211653 00204 LD HL,ramdisk ;Aufruf der RAM-Disk (kann entfallen) 5313 C30544 00205 JR 4405h ;als DOS-Befehl ausführen und ENDE 00206 5316 52 00207 ramdisk DM 'RAMDISK',Odh ;Page des RAM-Disk-Programms, CR 00208 00209 ;Tabelle der zu relozierenden Adressen in der TRAF-Routine 531E 1152 00210 addrtab DW addr1,addr2,addr3,addr4,addr5,addr6,addr7,addr8 532E 7352 00211 DW addr9,addr10,addr11,addr12,addr13,addr14,addr15 00212 endtab 00000 Fehler 00001 ;Listing 5: Ein geändertes SYS-File soll vor dem endgültigen Gebrauch 00002 ;SYSTEST/CMD in Bank 0 gepuffert und von dort aus getestet werden. 00003 6000 00004 ORG 6000h 00005 35BB 00006 dma EQU 35bbh ;DMA-Treiber 00007 6000 340B4C 00008 start LD 4,(4c0bh) ;bei depuffertem DOS steht dort 00 6003 87 00009 OR A ;ist das DOS in Bank 0 schon gepuffert? 6004 2807 00010 JR Z,go_baby ;alles klar, falls ja 6006 E5 00011 PUSH HL ;Befehlszeiger retten 6007 3EFC 00012 LD A,0fch ;Requestcode für SYS26: DOS erst bunkern 6009 CD0244 00013 CALL 4402h ;dort steht RST 28h für den DOS-Request 600C E1 00014 POP HL ;Befehlszeiger 600D CDD54C 00015 go_baby CALL 4cd5h ;HL auf nächsten Befehlsparameter stellen 6010 2006 00016 JR NZ,makefcb ;falls etwas folgt 6012 11AF60 00017 LD DE,filespc ;Text 'Name ..." 6015 CD9560 00018 CALL getinpt ;ausgeben, Dateinamen einlesen 6018 11E060 00019 makefcb LD DE,fcb ;FCB-Adresse 601B CD1C44 00020 CALL 441ch ;Dateinamen in den FCB übertragen 601E CD2044 00021 CALL 4420h ;FCB eröffnen 6021 206D 00022 JR NZ,errexit ;falls Fehler aufgetreten 6023 CDD54C 00023 CALL 4cd5h ;HL auf nächsten Befehlsparameter stellen 6026 2006 00024 JR NZ,getsys ;falls etwas folgt 6028 11C960 00025 LD DE,sysmbr ;Text 'SYS-File ..." 602B CD9560 00026 CALL getinpt ;ausgeben, SYS-Nr. einlesen 602E CD9F60 00027 getsys CALL getciph ;1. Ziffer binär umwandeln 6031 78 00028 LD A,8 ;Binärziffer 6032 280B 00029 JR Z,putsys ;falls Eingabe beendet (SYS1-9) 6034 0E0A 00030 LD C,0ah ;Faktor 10d für zweistellige Zahlen 00031 ; MLT BC ;BC = B * C: B <- 00, C <- 10*B 6036 ED 00032 DB 0edh,4ch ;Hex-Entsprechung des Befehls 6038 CD9F60 00033 CALL getciph ;2. Ziffer einlesen (muß letzte sein) 603B 2053 00034 JR NZ,errexit ;falls Eingabe noch nicht beendet 603D 78 00035 LD A,8 ;neue Ziffer (binär) 603E 81 00036 ADD A,C ;+ 10mal 1. Ziffer 603F 3C 00037 putsys INC A ;+2, weil GDOS und INHALT keine Nr. haben 6040 3C 00038 INC A 6041 FE03 00039 CP 03h ;SYS1? ('kleinste' erlaubte SYS-Datei) 6043 3849 00040 JR C,illnmbr ;Fehler: Eingabe von SYSO 6045 FE20 00041 CP 1fh+1 ;SY529? ('höchste' erlaubte SYS-Datei) 6047 3045 00042 JR NC,illnmbr ;falls Quatsch wie etwa SYS4711 6049 07 00043 RLCA ;'2, weil 2 Bytes pro Eintrag im SYS-DIR 604A 08 00044 EX AF,AF' ;retten 604B 210040 00045 LD HL,4000h ;dort in Bank 0 das SYS-DIR 604E 110080 00046 LD DE,8000h ;Puffer dafür in Bank 1 6051 05 00047 PUSH DE ;für später 6052 45 00048 LD B,L ;BC <- 0040h = 64d, Länge des SYS-DIR 6053 4C 00049 LD C,H 6054 3E10 00050 LD A,10h ;von Bank 0 nach Bank 1 6056 CDBB35 00051 CALL dma ;SYS-DIR in den Puffer übertragen 6059 08 00052 EX AF,AF' ;aufbereitete SYS-Nr. 605A 5F 00053 LD E,A ;DE <- Adresse des Eintrags im SYS-DIR 605B 1A 00054 LD A,(DE) ;MSB der Adresse des SYS-Files in Bank 0 605C 328560 00055 LD (sysaddr),A ;dort ablegen 605F 13 00056 INC DE ;auf Längenbyte (Blockzähler) stellen 6060 14 00057 LD A,(DE) ;laden 6061 5F 00058 LD E,A ;DE <- Länge des SYS-Files (LSB) 6062 55 00059 LD D,L ;MSB . 00 (max. 35 Sektoren bei SYS6) 6063 2AEC60 00060 LD HL,(fcb+0ch) ;2. u. 1. EOF-Byte, gibt Länge in Skt. an 6066 7D 00061 LD A,L ;Zähler für zu ladende Skt. (LS8 genügt) 6067 3C 00062 INC A ;0.1, weil ab 0 gezählt, Cy lösch. wg. SBC 6068 47 00063 LD B,A ;B als Zähler aufsetzen 6069 328860 00064 LD (bytecnt),A ;als DMA-Bytezähler (MSB) patchen 606C E052 00065 SBC HL,DE ;beide Filelängen vergleichen 606E 3E3B 00066 LD A,3bh ;Fehlercode 'unzureich. Speicherplatz' 6070 301E 00067 JR NC,errexit ;falls Testfile zu lang 6072 E1 00068 POP HL ;Puffer ab 8000h in Bank 1 6073 11E060 00069 LD DE,fcb ;Zeiger auf den FCB 6076 22E360 00070 ldloop LD (fcb+03h),HL ;Pufferadresse in den FCB schreiben 6079 24 00071 INC H ;Pufferzeiger 256 Bytes weiterstellen 607A CD3644 00072 CALL 4436h ;einen Sektor einlesen 607D 2011 00073 JR NZ,errexit ;falls ein Fehler auftrat 607F 10F5 00074 DJNZ ldloop ;bis alle Sektoren eingelesen sind 6081 2680 00075 LD H,8000h/256 ;HL <- Puffer 8000h in Bank 1 (LSB . 00) 6083 110000 00076 LD DE,0000h ;Zieladresse in Bank 0 (LSB immer 00) 6085 00077 sysaddr EQU $-1 ;MSB der SYS-Adresse in Bank 0 6086 010000 00078 LD BC,0000h ;Bytezähler (LSB immer 00) 6088 00079 bytecnt EQU $-1 ;MSB wird gepatcht 6089 3E01 00080 LD A,01h ;von Bank 1 nach Bank 0 6088 C3BB35 00081 JP dma ;neues SYS-File speichern und ENDE 00082 608E 3E29 00083 illnmbr LD A,29h ;Fehlercode 'unzul. log. Dateinummer' 6090 E67F 00084 errexit AND 7fh ;NZ-Bedingung (Fehler), keine Rückkehr 6092 C30944 03085 JP 4409h ;Fehlermeldung ausgeben und ENDE 00086 6095 EB 00087 getinpt EX DE,HL ;HL - Zeiger auf Text 6096 CD6744 00088 CALL 4467h ;Text anzeigen 6099 0620 00089 LD B,20h ;max. 32d Zeichen (sehr reichlich) 609B EB 00090 EX DE,HL ;HL - DOS-Eingabepuffer für Eingabe 609C C34000 00091 JP 0040h ;Eingabe einlesen und zurück 00092 609F 7E 00093 getciph LD A,(HL) ;Zeichen laden 60A0 FE30 00094 CP '0' ;kleinste erlaubte Ziffer? 60A2 38EA 00095 JR C,illnmbr ;Fehler, falls kleiner 60A4 FE3A 00096 CP '9'+1 ;größte erlaubte Ziffer? 60A6 30E6 00097 JR NC,illnmbr ;Fehler, falls größer 60A8 E60F 00098 AND 0fh ;ASCII -) binär 60AA 47 00099 LD B,A ;Eingabe binär puffern 60AB 23 00100 INC HL ;Befehlszeiger nachstellen 60AC C3D54C 00101 JP 4cd5h ;nächsten Befehlsparam. holen und zurück 00102 00103 ;verschiedene Texte und Puffer 60AF 4E 00104 filespc DM 'Name des Testprogramms? ',0eh,03h ;Text, Churs., EOS 60C9 53 00105 sysnsbr DM 'SYS-File-Nr.',09h,'(1-29)? ',0eh,03h ;dto. mit TAB 00106 fcb ;Puffer für FCB 00107 6000 00108 END start 00000 Fehler

Anhang

Probleme mit den Illegals

Geralds Trap-Programm ist eine wertvolle Hilfe, dennoch kein Allheilmittel. Von den vielen denkbaren Illegals, die im Code-Muster des Z80 stecken, sind längst nicht alle bereits entschlüsselt und dokumentiert. Die Trap-Routine müßte daher bei jeder neuen Entdeckung aktualisiert werden.

Und der Z180 benutzt selber für seine neuen Befehle solche ehemals weißen Stellen in der Code-Matrix des Z80. Glücklicherweise beschieden sich seine Designer mit solchen Codes, die mit dem Switch-Byte EDh beginnen, so daß ein notwendiges Debugging verdächtiger Programme in Grenzen bleibt. Nämlich auch Illegals mit EDh werden schon irgendetwas beim Z80 bewirken, was auch immer. Die Illegal-Trap-Routine würde in diesem Falle überhaupt nicht angesprungen, denn es wäre für den Z180 ja ein sinnvoller Befehl.

Einer dieser beiden Gründe wird es wohl sein, weshalb nach der Umrüstung des G3s auf den Z180 ausgerechnet mit ZEUS/CMD zahlreiche Abstürze auftraten. Aber vielleicht wurde auch Geralds Programm falsch abgetippt. Egal - es mußte etwas geschehen, denn mit ZEUS steht und fällt die Soft-Seite des ganzen Unternehmens:

DSMBLR ist ein Disassembler, der gottlob keine Illegals akzeptiert, wie es z. B. ZEUS durchaus tut. Wenn man daher ein Programm disassembliert, das Illegals enthält, zuckt DSMBLR ratlos die Achseln und setzt DM-(DEFM-) Statements, wo er in seinem Vorrat keinen Z80-Befehl findet (DSMBLR und ZEUS behandeln DB und DM gleich, soweit es sich um einzelne Bytes handelt).

So haben wir ZEUS ohne jegliches Screening disassembliert und nach DMs gesucht. An vier Stellen wurden wir fündig (Listing 6). In einem gesonderten File, mit dem wir seit jeher ZEUS patchen (ZAPZEUS/CMD, Listing 7), wurden Simulationen der Illegals programmiert, in ZEUS selbst CALLs nach dort gepatcht.

ZAPZEUS (für diesen Zweck genügen die gelisteten Teile) kann so abgetippt und auf Papier assembliert werden. Die Bestandteile bis Zeile 46 werden etwa mit Hilfe von FED/CMD, mitten in ZEUS gezapt. Was dahinter liegt, muß im letzten Sektor von ZEUS angehängt werden. Der Ende-String (02-02-xy-xx) wird als neuer Record-Header (01-nn-yy-xx) geändert. Das Anhängsel-Programm bringt seinen eigenen Ende-String mit. Dafür ist es wichtig, daß seine Einsprungsadresse (END addr) die von ZEUS sein muß (s. Listing).

Ob damit alles erledigt ist, muß die zukünftige Praxis zeigen. Ohne ein Screening-File für DSMBLR werden nämlich Texte und Tabellen wie Programmcode disassembliert. So ergeben sich Verschiebungen im "Programm"-Ablauf, die etwa ein Illegal-Switch-Byte wie einen harmlosen Bestandteil eines Sprungbefehls (Adresse, Distanz) erscheinen lassen können. Da das aber nur auftreten kann, wenn ein Illegal direkt an einen reinen Datenblock grenzt, darf man mit Recht auf Erfolg hoffen.

Auch das Gegenteil wäre eine mögliche Fehlerquelle: Eine Tabelle, die ohne Screening ja nicht als solche behandelt wird, enthält ein verdächtiges Byte. Der Zufall will es, daß der Inhalt der Tabelle wie sinnvoller Programmcode aussieht. Ein dort gepatchter CALL würde die Tabelle verfälschen. Wir können nur raten, in solchen Fällen die betreffenden Stellen ganz besonders sorgfältig zu untersuchen ...

... und unbedingt das Ergebnis zur Veröffentlichung an Jens-80 Neueder zu schicken!


		00001 ;Listing 6:	Illegals in ZEUS/CMD
		00002 ;ZEUS/CMD	(hier nicht interessierende Teile sind mit LIST OFF
		00003 ;	ausgespart - erkennbar an den springenden Zeilennummern)
		00004 
		; mit LIST OFF ausgespart
52E7 DD		00305		DM	Oddh		;DD 7D:'
52E8 7D		00306		LD	A,L		;LD A,LX
52E9 FE28	00307		CP	'+'
		00308 
5809 CB		00694		DM	0cbh		;CB 31 06 01:
580A 310601	00695		LD	SP,m0106	;SLIA C - LD 8,01
		00696 
5045 C8		00731		DM	0cbh		;C3 31 06 01:
5846 310601	00732		LD	SP,m0106	;SLIA C - LD 8,01
		00733 
64E9 CB		00700		DM	0cbh		;CB 37:
6AEA 37		00701		SCF			;SLIA A
		00702
00000 Fehler
		; mit LIST OFF ausgespart
		00001 ;Listing 7:	Illegal-Trap direkt in ZEUS/CMD
		00002 ;ZAPZEUS/CMD	(hier nicht interessierende Teile sind mit LIST 0FF
		00003 ;ausgespart - erkennbar an den springenden Zeilennummern)
		; mit LIST OFF ausgespart
		00034
52E7		00035		ORG	52e7h		;dort Illegal LD A,LX
52E7 CD2830	00036		CALL	ld_a_1x		;simulieren
		00037
5809		00038		ORG	5b09h		;dort Illegal SLIA C
5809 CD3330	00039		CALL	slia_c		;simulieren
		00040
5845		00041		ORG	5b45h		;dort Illegal SLIA C
5845 CD3330	00042		CALL	slia_c		;simulieren
		00043
6AE9		00044		ORG	6ae9h		;dort Illegal SLIA A
6AE9 37		00045		SCF			;Cy für Bit 0 setzen
6AEA 17		00046		RLA			;rotieren
		; mit LIST OFF ausgespart
		00076
3000		00077		ORG	3000h		;wo es nicht stört
		; mit LIST OFF ausgespart
		00106
3028 DDE5	00107 ld_a_1x	PUSH	IX		;auf den Stack
302A E3		00108		EX	(SP),HL		;HL retten, HL - IX
3028 7D		00109		LD	A,L		;A - LX
302C E3		00110		EX	(SP),HL		;HL und IX restaurieren
302D DDE1	00111		POP	IX
302F F2BH	00112		CP	2bh		;überschriebenen Befehl nachholen
3031 1B05	00113		JR	return		;zurück zur Fortsetzung
		00114
3033 CB21	00115 slia_c	SLA	C		;C shiften
3035 0C		00116		INC	C		;Bit 0 setzen
3036 0601	00117		LD	B,01h		;überschriebenen Befehl nachholen
		00118
3038 E3		00119 return	EX	(SP),HL		;HL - RET-Adresse
3039 23		00120		INC	HL		;ein Byte später
303A E3		00121		EX	(SP),HL		;zurücktauschen
303B C9		00122		RET			;an die neue Adresse zurückkehren
		00123
5312		00124		END	5312h		;hier Einsprung in ZEUS
00000 Fehler